/*
   Copyright (C) 2009 Geoffrey Hausheer

This file is part of gpsim.

gpsim is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

gpsim is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with gpsim; see the file COPYING.  If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */

/*

  push_button.cc


*/

/* IN_MODULE should be defined for modules */
#define IN_MODULE

#include <time.h>
#include <stdio.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <errno.h>
#include <stdlib.h>
#include <string>
#include <iostream>

//#include "../config.h"    // get the definition for HAVE_GUI
#ifdef HAVE_GUI

#include <gtk/gtk.h>

#include <gpsim/packages.h>
#include "analog_source.h"

//----------------------------------------
class AnalogVAttribute : public Float {

public:
  AnalogSource *an;


  AnalogVAttribute(AnalogSource *pan) 
    : Float("voltage",0.0,"voltage of analog source"),
      an(pan)
  {
    if(an)
      Float::set((an->anlg_pin)->get_Vpullup());
  }


  virtual void set(double v) {

    Float::set(v);

    if(an) {
      an->anlg_pin->set_Vpullup(v);
      an->anlg_pin->updateNode();
      an->updateSlider(v);
    }
  };

  void set_only(double v) {
    Float::set(v);

    if(an) {
      an->anlg_pin->set_Vpullup(v);
      an->anlg_pin->updateNode();
    }
  };

  void set(int r) {
    Float::set((double)r);
  };
};

//--------------------------------------------------------------
// create_iopin_map 
//
//  This is where the information for the Module's package is defined.
// Specifically, the I/O pins of the module are created.

void AnalogSource::create_iopin_map(void)
{

  create_pkg(1);

  assign_pin(1, anlg_pin);
  package->set_pin_position(1,2.5); // Position pin on middle right side of package

}

//--------------------------------------------------------------
// GUI
static void
scale_cb (GtkWidget *scale, AnalogSource *as)

{
  double v;
  if (as && as->anlg_pin) {
    v = gtk_range_get_value(GTK_RANGE(scale));
    printf("Setting voltage to: %f\n", v);
    as->vattr->set_only(v);
  }
}

void
AnalogSource::updateSlider(double v)

{
  if(scale)
    gtk_range_set_value(GTK_RANGE(scale), v);
}

void AnalogSource::create_widget(AnalogSource *as)
{

  GtkWidget	*box1;
	
  box1 = gtk_vbox_new (FALSE, 0);

  scale = gtk_vscale_new_with_range(0, 5.0, 0.001);
  gtk_scale_set_digits(GTK_SCALE(scale), 3);
  gtk_widget_set_size_request(scale, -1, 200);
  gtk_range_set_inverted(GTK_RANGE(scale), 1);

  gtk_signal_connect (GTK_OBJECT (scale), "value_changed",			    
		      GTK_SIGNAL_FUNC (scale_cb), (gpointer)as);
		
  gtk_widget_show(scale);
  gtk_box_pack_start (GTK_BOX (box1), scale, FALSE, FALSE, 0);
	
	
  // Tell gpsim which widget to use in breadboard.
  as->set_widget(box1);
}

//--------------------------------------------------------------
// construct
Module * AnalogSource::construct(const char *_new_name=0)
{

  AnalogSource *anlgP = new AnalogSource(_new_name) ;

  anlgP->create_widget(anlgP);

  return anlgP;

}

AnalogSource::AnalogSource(const char * _name) : Module(_name, "AnalogSource")
{
  scale = NULL;
  anlg_pin = new IO_bi_directional_pu((name() + ".pin").c_str());

  create_iopin_map();

  vattr = new AnalogVAttribute(this);
  addSymbol(vattr);

  anlg_pin->set_Zpullup(100);
  anlg_pin->set_Cth(0);
  anlg_pin->setDriving(false);
  anlg_pin->update_pullup('1',true);
  vattr->set(anlg_pin->get_Vth());
}

AnalogSource::~AnalogSource(void)
{
  removeSymbol(vattr);
  delete anlg_pin;
}
#endif // HAVE_GUI
